import os
import tempfile
from datetime import datetime
from urllib.parse import urlparse, urlunparse

import validators
from werkzeug.utils import secure_filename

from common import bucket
from config import config_settings
from models.biz_enum import FileType

# 允许的文件类型
IMAGE_ALLOWED_EXTENSIONS = {'png', 'jpg', 'jpeg', 'gif'}

# 允许的文件类型
VIDEO_ALLOWED_EXTENSIONS = {'mp4'}


def image_allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in IMAGE_ALLOWED_EXTENSIONS


def video_allowed_file(filename):
    return '.' in filename and \
        filename.rsplit('.', 1)[1].lower() in VIDEO_ALLOWED_EXTENSIONS


def generate_new_filename(original_filename, file_type=''):
    """生成新的文件名"""
    import uuid
    from datetime import datetime

    # 获取文件扩展名
    extension = original_filename.rsplit('.', 1)[1].lower() if '.' in original_filename else ''

    # 生成时间戳和随机UUID组合的新文件名
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    random_str = str(uuid.uuid4())[:8]

    if extension:
        new_name = f"{timestamp}_{random_str}.{extension}"
    else:
        new_name = f"{timestamp}_{random_str}"

    folder = ''
    if file_type == FileType.IMAGE:
        folder = f"{config_settings.OSS_CONFIG['image_folder']}/"
    elif file_type == FileType.VIDEO:
        folder = f"{config_settings.OSS_CONFIG['video_folder']}/"

    filename = f"{folder}{secure_filename(new_name)}"

    return filename


def upload_file(file, file_type, filename=""):
    try:
        # 生成唯一文件名
        if not filename:
            filename = generate_new_filename(file.filename, file_type)

        print(f"filename: {filename}")

        # 上传到OSS
        result = bucket.put_object(filename, file)

        if result.status == 200:
            # 构建文件URL
            file_url = get_file_url(filename)
            return filename, file_url
        else:
            return ""

    except Exception as e:
        print(e)
        return ""


def async_upload_to_oss(filename, local_path):
    try:
        # 上传到OSS
        result = bucket.put_object_from_file(filename, local_path)

        # 上传完成后删除本地临时文件
        os.remove(local_path)

        return dict(status=result.status)

    except Exception as e:
        print(e)
        return dict(status=400)


def upload_file_async(file, file_type, filename=""):
    try:
        # 生成唯一文件名
        if not filename:
            filename = generate_new_filename(file.filename, file_type)

        print(f"filename: {filename}")

        # 生成临时文件路径
        temp_filename = generate_new_filename(file.filename)
        temp_dir = tempfile.gettempdir()
        temp_file_path = os.path.join(temp_dir, temp_filename)
        file.save(temp_file_path)

        # 提交异步任务
        task = async_upload_to_oss.delay(filename, temp_file_path)

        return filename, temp_file_path

    except Exception as e:
        print(e)
        return ""


def get_relative_path_by_url(url):
    parsed = urlparse(url)
    if parsed.path[0] == '/':
        return parsed.path[1:]
    else:
        return parsed.path


def replace_file(original_file_name, new_file_name):
    try:
        if validators.url(original_file_name):
            original_file_name = get_relative_path_by_url(original_file_name)

        if validators.url(new_file_name):
            new_file_name = get_relative_path_by_url(new_file_name)

        # 生成临时文件路径
        temp_dir = tempfile.gettempdir()
        temp_file_path = os.path.join(temp_dir, secure_filename(new_file_name))

        # 下载新文件到临时目录
        bucket.get_object_to_file(new_file_name, temp_file_path)

        # 覆盖原始文件
        with open(temp_file_path, 'rb') as file_obj:
            upload_result = bucket.put_object(original_file_name, file_obj)

        # 清理临时文件
        if os.path.exists(temp_file_path):
            os.remove(temp_file_path)

        # 删除新文件
        bucket.delete_object(new_file_name)

        if upload_result.status == 200:
            return "success"
        else:
            return ""

    except Exception as e:
        print(e)
        return ""


def get_file_url(object_name, expires=None):
    if not expires:
        expires = config_settings.OSS_CONFIG['expires']
    return bucket.sign_url('GET', object_name, expires, slash_safe=True)
